package com.nullpointer.xchat;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.simonvt.menudrawer.MenuDrawer;
import net.simonvt.menudrawer.MenuDrawer.OnDrawerStateChangeListener;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Vibrator;
import android.provider.Settings;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.LocalBroadcastManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.LayoutParams;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;
import com.nullpointer.xchat.adapter.ChatPrivateAdapter;
import com.nullpointer.xchat.adapter.ChatRoomAdapter;
import com.nullpointer.xchat.adapter.EmoticonAdapter;
import com.nullpointer.xchat.adapter.HistoryMessageAdapter;
import com.nullpointer.xchat.adapter.UserAdapter;
import com.nullpointer.xchat.database.MessagesDataManager;
import com.nullpointer.xchat.fragment.ChooseImageDialogFragment;
import com.nullpointer.xchat.fragment.ChooseImageDialogFragment.OnChooseImageDialogFragment;
import com.nullpointer.xchat.fragment.ChooseRoomDialogFragment;
import com.nullpointer.xchat.fragment.DeleteMessageDialogFragment;
import com.nullpointer.xchat.fragment.DeleteMessageDialogFragment.onDeleteMessagesDialogFragment;
import com.nullpointer.xchat.fragment.EditProfileDialogFragment;
import com.nullpointer.xchat.fragment.ExitConfirmDialogFragment;
import com.nullpointer.xchat.fragment.ExitConfirmDialogFragment.OnExitDialogListener;
import com.nullpointer.xchat.fragment.FindFriendResultsFragment;
import com.nullpointer.xchat.fragment.FindFriendSettingDialogFragment;
import com.nullpointer.xchat.fragment.LogoutConfirmDialogFragment;
import com.nullpointer.xchat.fragment.LogoutConfirmDialogFragment.OnLogoutDialogListener;
import com.nullpointer.xchat.fragment.SayHiDialogFragment;
import com.nullpointer.xchat.fragment.SayHiDialogFragment.OnSayHiDialogFragment;
import com.nullpointer.xchat.fragment.SettingDialogFragment;
import com.nullpointer.xchat.fragment.SettingDialogFragment.OnSettingDialogFragment;
import com.nullpointer.xchat.fragment.ViewProfileFragment;
import com.nullpointer.xchat.object.HistoryMessage;
import com.nullpointer.xchat.object.MainDisplayState;
import com.nullpointer.xchat.object.MessageContent;
import com.nullpointer.xchat.object.MessageContent.MsgType;
import com.nullpointer.xchat.object.RoomType;
import com.nullpointer.xchat.object.SaveStateConfig;
import com.nullpointer.xchat.object.User;
import com.nullpointer.xchat.object.UserInfo;
import com.nullpointer.xchat.object.UserInfo.GenderType;
import com.nullpointer.xchat.service.ChatService;
import com.nullpointer.xchat.utils.Common;
import com.nullpointer.xchat.utils.DataManager;
import com.nullpointer.xchat.utils.Emoticons;
import com.nullpointer.xchat.utils.KiraGameLog;
import com.nullpointer.xchat.utils.TextFilter;
import com.nullpointer.xchat.utils.Utils;
import com.quickblox.core.Consts;
import com.quickblox.core.QBEntityCallbackImpl;
import com.quickblox.core.request.QBPagedRequestBuilder;
import com.quickblox.users.QBUsers;
import com.quickblox.users.model.QBUser;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelSlideListener;

public class MainActivity extends SherlockFragmentActivity {

	// FLOWS: SETUP SERVER ->JOIN ROOM
	// -> CHECK PROFILE AND UPDATE
	// -> LOAD SUGGESTED USER
	//
	//
	// IN ROOM
	// Layout
	private MenuDrawer mDrawerMessages;
	private ActionBar mActionBar;

	private ListView lvChat;
	private EditText etMessage;
	private ImageButton btSend;
	private ListView lvUsers;
	private GridView gvEmoticons;
	private ImageButton btEmoticon;
	private ImageButton btImage;
	private SlidingUpPanelLayout slidingLayout;
	private Button btFindchat;
	private ImageButton btFindFriendSetting;
	private TextView tvTyping;

	private static final long TIME_SHOW_ADS = 1000 * 60 * 1;

	// SNACK BAR
	private LinearLayout llNotice;
	private ProgressBar pbLoading;
	private TextView tvNotice;
	private View vSplit;
	private TextView tvAction;
	private Animation animationShow;
	private Animation animationHide;
	private Animation animationRotate;

	// Actionbar
	private ImageButton ibProfile;
	// private Spinner snRoom;
	private ImageButton ibOption;
	private RelativeLayout rlMessages;
	private TextView tvNumMessage;
	private TextView tvTitle;
	private ImageButton ibOnline;
	private ImageButton ibRefresh;

	// MESSAGES FRAGMENT
	private ListView lvMessages;
	private ImageButton ibLogout;
	private TextView tvMessageRoomMessageHistory;
	private TextView tvMessageNumRoomMessageHistory;
	private Button btSetting;
	private ImageButton btClearMessage;
	private LinearLayout llRoomMessageHistory;
	private List<HistoryMessage> historyMessageData = new ArrayList<HistoryMessage>();
	private HistoryMessageAdapter historyMessageAdapter;

	private int newRoomMessageHistory = 0;

	// CHAT IN ROOM
	private List<MessageContent> messageContentRoomData = new ArrayList<MessageContent>();
	private ChatRoomAdapter chatRoomAdapter;

	// USER IN ROOM
	private List<User> userData = new ArrayList<User>();
	private UserAdapter userAdapter;

	private Set<Integer> currentUserIDsInList = new HashSet<>();

	private Set<Integer> findUserIDInList = new HashSet<>();

	// CHAT PRIVATE
	private List<MessageContent> messageContentPrivateData = new ArrayList<MessageContent>();
	private ChatPrivateAdapter chatPrivateAdapter;

	private boolean isTyping = false;

	// COMMON
	private MainDisplayState mDisplayState = MainDisplayState.ROOM_STATUS;
	private Vibrator vibrator;

	private boolean isFindingChat = false;

	// private RoomType currentRoom = RoomType.ENGLISH;

	private final long FIND_FRIEND_TIME_OUT = 1000 * 10;

	// Saved Instance State
	private final String SAVE_STATE_CONFIG = "SAVE_STATE_CONFIG";

	private String currentChatName;

	// private boolean isShowChat = false;
	private AdView mAdViewMain;
	private AdView mAdViewChat;
	private InterstitialAd interstitial;
	private CountDownTimer mCountDownTimer;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		KiraGameLog.d("-------- onCreate --------");
		settingActionbar();
		settingSlidingMessages();
		findViews();
		init();
		setEvent();
	}

	private void checkViewNotify() {
		Integer userID = DataManager.getInstance(this).getNotifyUserId();
		String userName = DataManager.getInstance(this).getNotifyUserName();

		if (userID != null && userName != null) {
			showChatPrivate(userID, userName, true);
			DataManager.getInstance(this).setNotifyUserId(null);
			DataManager.getInstance(this).setNotifyUserName(null);
		}
	}

	@Override
	protected void onSaveInstanceState(Bundle savedInstanceState) {
		super.onSaveInstanceState(savedInstanceState);
		SaveStateConfig config = new SaveStateConfig();
		config.setCurrentChatUserName(currentChatName);
		config.setmDisplayState(mDisplayState);
		savedInstanceState.putString(SAVE_STATE_CONFIG, config.toJson());
		KiraGameLog.d("onSaveInstanceState SAVE_STATE_CONFIG: "
				+ config.toJson());
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);

		SaveStateConfig config = SaveStateConfig
				.fromJsonToSaveStateConfig(savedInstanceState
						.getString(SAVE_STATE_CONFIG));

		currentChatName = config.getCurrentChatUserName();
		mDisplayState = config.getmDisplayState();

		KiraGameLog.d("onRestoreInstanceState SAVE_STATE_CONFIG: "
				+ config.toJson());

		changeActionBarState(mDisplayState);

		if (mDisplayState == MainDisplayState.CHAT_PRIVATE) {
			showChatPrivate(DataManager.getInstance(this)
					.getCurrentChatUserId(), currentChatName, true);
		} else if (mDisplayState == MainDisplayState.CHAT_ROOM) {
			showChatRoom();
		} else {
			slidingLayout.collapsePanel();
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode,
			Intent itent) {
		super.onActivityResult(requestCode, resultCode, itent);
		switch (requestCode) {
		case Common.RequestCode.CHAT_IMAGE:
			if (resultCode == RESULT_CANCELED) {
				return;
			}
			String url = itent.getStringExtra(ProcessImage.IMAGE_URL);
			sendImageChat(url);
			break;
		}
	}

	@Override
	public void onBackPressed() {
		if (mDrawerMessages.isMenuVisible()) {
			mDrawerMessages.toggleMenu();
		} else if (gvEmoticons.getVisibility() == View.VISIBLE) {
			gvEmoticons.setVisibility(View.GONE);
		} else if (slidingLayout != null && slidingLayout.isPanelExpanded()
				|| slidingLayout.isPanelAnchored()) {
			slidingLayout.collapsePanel();
		} else {
			// super.onBackPressed();
			showExitDialog();
		}
	}

	@Override
	protected void onDestroy() {
		KiraGameLog.d("--------- onDestroy ---------");
		try {
			LocalBroadcastManager.getInstance(this).unregisterReceiver(
					changeUIReceiver);

			if (mAdViewMain != null) {
				mAdViewMain.destroy();
			}

			if (mAdViewChat != null) {
				mAdViewChat.destroy();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		super.onDestroy();
	}

	@Override
	protected void onStop() {
		KiraGameLog.d("--------- onStop ---------");
		super.onStop();
	}

	@Override
	protected void onPause() {
		KiraGameLog.d("--------- onPause ---------");
		sendChatStopTyping();
		DataManager.getInstance(this).setIsShowNotify(true);
		if (mAdViewMain != null) {
			mAdViewMain.pause();
		}

		if (mAdViewChat != null) {
			mAdViewChat.pause();
		}

		if (mCountDownTimer != null) {
			mCountDownTimer.cancel();
		}
		super.onPause();
	}

	@Override
	protected void onResume() {
		super.onResume();
		KiraGameLog.d("--------- onResume ---------");
		checkAccoutnAndChatServiceAlive(false);
		DataManager.getInstance(this).setIsShowNotify(false);
		checkViewNotify();
		if (mDisplayState == MainDisplayState.CHAT_PRIVATE) {
			lvChat.setSelection(messageContentPrivateData.size() - 1);
		} else {
			lvChat.setSelection(messageContentRoomData.size() - 1);
		}

		if (mAdViewMain != null) {
			mAdViewMain.resume();
		}

		if (mAdViewChat != null) {
			mAdViewChat.resume();
		}
	}

	@Override
	public void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		KiraGameLog.d("--------- onDetachedFromWindow ---------");
	}

	private void settingSlidingMessages() {
		mDrawerMessages = MenuDrawer.attach(this);
		mDrawerMessages.setContentView(R.layout.activity_main);
		mDrawerMessages.setMenuView(getMessagesView());
		mDrawerMessages.setDropShadowColor(Color.parseColor("#ff8800"));
		mDrawerMessages.setDropShadowSize(1);
		int width = 2 * (getResources().getDisplayMetrics().widthPixels / 3);
		mDrawerMessages.setMenuSize(width);
	}

	private void settingActionbar() {
		View customView = getActionbarView();
		LayoutParams layout = new LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT);
		mActionBar = getSupportActionBar();
		mActionBar.setCustomView(customView, layout);
		// mActionBar.hide();
		mActionBar.setDisplayShowHomeEnabled(false);
		mActionBar.setDisplayHomeAsUpEnabled(false);
		mActionBar.setDisplayShowCustomEnabled(true);
		mActionBar.setDisplayShowTitleEnabled(false);
		// mActionBar.setCustomView(getActionbarView());
		mActionBar.show();
	}

	private View getActionbarView() {
		View view = getLayoutInflater().inflate(R.layout.actionbar_main, null);
		ibProfile = (ImageButton) view.findViewById(R.id.ib_profile);
		// snRoom = (Spinner) view.findViewById(R.id.sn_room);
		rlMessages = (RelativeLayout) view.findViewById(R.id.rl_messages);
		tvNumMessage = (TextView) view.findViewById(R.id.tv_num_message);
		ibOption = (ImageButton) view.findViewById(R.id.ib_option);
		tvTitle = (TextView) view.findViewById(R.id.tv_title);
		ibOnline = (ImageButton) view.findViewById(R.id.ib_online);
		ibRefresh = (ImageButton) view.findViewById(R.id.ib_refresh);
		return view;
	}

	private void findViews() {
		tvNotice = (TextView) findViewById(R.id.tv_notice);
		lvChat = (ListView) findViewById(R.id.lv_chat);
		etMessage = (EditText) findViewById(R.id.et_message);
		btSend = (ImageButton) findViewById(R.id.bt_send);
		slidingLayout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout);
		lvUsers = (ListView) findViewById(R.id.lv_users);
		gvEmoticons = (GridView) findViewById(R.id.gv_emoticons);
		btEmoticon = (ImageButton) findViewById(R.id.bt_emoticon);
		btImage = (ImageButton) findViewById(R.id.bt_image);
		llNotice = (LinearLayout) findViewById(R.id.ll_notice);
		pbLoading = (ProgressBar) findViewById(R.id.pbLoading);
		tvNotice = (TextView) findViewById(R.id.tv_notice);
		vSplit = (View) findViewById(R.id.v_split);
		tvAction = (TextView) findViewById(R.id.tv_action);
		btFindchat = (Button) findViewById(R.id.bt_findchat);
		mAdViewMain = (AdView) findViewById(R.id.adViewMain);
		mAdViewChat = (AdView) findViewById(R.id.adViewChat);
		tvTyping = (TextView) findViewById(R.id.tv_typing);
		btFindFriendSetting = (ImageButton) findViewById(R.id.bt_find_friend_setting);
	}

	private void init() {

		ibRefresh.setEnabled(false);
		changeActionBarState(mDisplayState);
		DataManager.getInstance(this).setCurrentChatUserId(null);
		animationRotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
		animationShow = AnimationUtils.loadAnimation(this,
				R.anim.snackbar_show_animation);
		animationHide = AnimationUtils.loadAnimation(this,
				R.anim.snackbar_hide_animation);
		vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
		lvChat.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
		lvChat.setStackFromBottom(true);
		btSend.setEnabled(false);

		// Default display chat room
		chatRoomAdapter = new ChatRoomAdapter(this, messageContentRoomData);
		lvChat.setAdapter(chatRoomAdapter);

		// Switch to chat private
		chatPrivateAdapter = new ChatPrivateAdapter(this,
				messageContentPrivateData);

		userAdapter = new UserAdapter(this, userData);
		lvUsers.setAdapter(userAdapter);

		EmoticonAdapter emoticonAdapter = new EmoticonAdapter(this);
		gvEmoticons.setAdapter(emoticonAdapter);
		slidingLayout.setDragView(new View(this));

		IntentFilter filter = new IntentFilter(ChatService.BROADCAST_NAME_MAIN);
		LocalBroadcastManager.getInstance(this).registerReceiver(
				changeUIReceiver, filter);
		initAds();
		checkAccoutnAndChatServiceAlive(true);
	}

	private void checkAccoutnAndChatServiceAlive(boolean isLoadData) {
		KiraGameLog.d("checkAccoutnAndChatServiceAlive");
		if (DataManager.getInstance(this).isLogout()
				|| (ChatService.getInstance() == null)
				|| ((ChatService.getInstance() != null) && !ChatService
						.getInstance().isLogin())) {
			startSplashActivity();
			finish();
		} else {
			if (!isLoadData) {
				return;
			}
			RoomType currentRoom = DataManager.getInstance(this)
					.getCurrentRoom();
			ChatService.getInstance().joinroom(
					Common.listRoomId[currentRoom.ordinal()], true);
			boolean isInvisible = DataManager.getInstance(this)
					.getInvisibleSetting();
			RoomType room = DataManager.getInstance(this).getCurrentRoom();
			ChatService.getInstance().updateProfile(true, isInvisible, room);
			clearUserData();
			getSuggestedUserOnline(1, 100);
			sendCheckFriendsOnline();
		}
	}

	private void startSplashActivity() {
		Intent intent = new Intent(this, SplashActivity.class);
		startActivity(intent);
	}

	private void initAds() {
		AdRequest adRequest = new AdRequest.Builder().addTestDevice(
				"CD3CF46DD6F23B701659BBF61B94EA51").build();

		// Start loading the ad in the background.
		mAdViewMain.loadAd(adRequest);
		mAdViewChat.loadAd(adRequest);

		// Create the interstitial.
		interstitial = new InterstitialAd(this);
		interstitial.setAdUnitId(getResources().getString(
				R.string.interstitial_id));

		// Create ad request.
		AdRequest interstitialAdRequest = new AdRequest.Builder()
				.addTestDevice("CD3CF46DD6F23B701659BBF61B94EA51").build();

		// Begin loading your interstitial.
		interstitial.loadAd(interstitialAdRequest);
	}

	// Invoke displayInterstitial() when you are ready to display an
	// interstitial.
	public void displayInterstitial() {
		if (interstitial.isLoaded()
				&& DataManager.getInstance(this).getCurrentChatUserId() == null) {
			interstitial.show();
		}
		if (mCountDownTimer != null) {
			mCountDownTimer.cancel();
		}
	}

	private void initAdsTimer() {
		if (mCountDownTimer != null) {
			mCountDownTimer.cancel();
		}
		mCountDownTimer = new CountDownTimer(TIME_SHOW_ADS, 1000) {
			@Override
			public void onTick(long millisUnitFinished) {
				KiraGameLog.d("millisUnitFinished to show ads "
						+ millisUnitFinished);
			}

			@Override
			public void onFinish() {
				displayInterstitial();
			}
		}.start();
	}

	private void changeActionBarState(MainDisplayState mainDisplayState) {
		if (mainDisplayState == MainDisplayState.ROOM_STATUS) {
			tvTitle.setText("Suggested Friends");
			ibOnline.setVisibility(View.GONE);
			ibProfile.setVisibility(View.VISIBLE);
			ibOption.setVisibility(View.GONE);
			ibRefresh.setVisibility(View.VISIBLE);
		} else if (mainDisplayState == MainDisplayState.CHAT_PRIVATE) {
			// ibOnline.setVisibility(View.VISIBLE);
			ibProfile.setVisibility(View.GONE);
			ibOption.setVisibility(View.VISIBLE);
			ibRefresh.setVisibility(View.GONE);
		} else if (mainDisplayState == MainDisplayState.CHAT_ROOM) {
			RoomType currentRoom = DataManager.getInstance(this)
					.getCurrentRoom();
			tvTitle.setText("Chat Room("
					+ Common.listRoomName[currentRoom.ordinal()] + ")");
			ibOnline.setVisibility(View.GONE);
			ibProfile.setVisibility(View.GONE);
			ibOption.setVisibility(View.VISIBLE);
			ibRefresh.setVisibility(View.GONE);
		}

	}

	private void setEvent() {
		btSend.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String message = etMessage.getText().toString();
				etMessage.setText("");
				if (mDisplayState == MainDisplayState.CHAT_ROOM) {
					// Chat room
					ChatService.getInstance().sendMessageChatRoom(
							TextFilter
									.getFilterText(MainActivity.this, message),
							MsgType.TEXT);
					// lvChat.setSelection(chatPrivateAdapter.getCount() - 1);

				} else if (mDisplayState == MainDisplayState.CHAT_PRIVATE) {
					// Chat private
					Integer chatToUser = DataManager.getInstance(
							MainActivity.this).getCurrentChatUserId();
					if (chatToUser == null) {
						return;
					}
					ChatService.getInstance().sendMessage(chatToUser, message,
							MsgType.TEXT, true);
					// lvChat.setSelection(chatRoomAdapter.getCount() - 1);
				} else {
					return;
				}
			}
		});

		lvChat.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				if (mDisplayState == MainDisplayState.CHAT_PRIVATE) {
					return;
				}
				MessageContent messageContent = (MessageContent) parent
						.getAdapter().getItem(position);
				showChatPrivate(messageContent.getFromUserID(),
						messageContent.getName(), false);
			}
		});

		etMessage.setOnFocusChangeListener(new OnFocusChangeListener() {

			@Override
			public void onFocusChange(View v, boolean hasFocus) {
				if (hasFocus) {
					gvEmoticons.setVisibility(View.GONE);
				}
			}
		});

		etMessage.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {

			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {

			}

			@Override
			public void afterTextChanged(Editable s) {
				int lenght = etMessage.getText().toString().trim().length();
				if (lenght > 0) {
					if ((mDisplayState == MainDisplayState.CHAT_PRIVATE)) {
						sendChatTyping();
					}
					btSend.setEnabled(true);
				} else {
					btSend.setEnabled(false);
				}
			}
		});
		gvEmoticons.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				etMessage.append(Emoticons.getSmiledText(MainActivity.this,
						Common.emoticonsName[position]));
			}
		});

		btEmoticon.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (gvEmoticons.getVisibility() == View.GONE
						|| gvEmoticons.getVisibility() == View.INVISIBLE) {
					gvEmoticons.setVisibility(View.VISIBLE);
					Utils.hideKeyboard(MainActivity.this, etMessage);
					lvChat.requestFocus();
				} else {
					gvEmoticons.setVisibility(View.GONE);
					etMessage.requestFocus();
					Utils.showKeyboard(MainActivity.this, etMessage);
				}
			}
		});
		slidingLayout.setPanelSlideListener(new PanelSlideListener() {

			@Override
			public void onPanelSlide(View panel, float slideOffset) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onPanelHidden(View panel) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onPanelExpanded(View panel) {
				changeActionBarState(mDisplayState);
			}

			@Override
			public void onPanelCollapsed(View panel) {
				initAdsTimer();
				// isShowChat = false;
				mDisplayState = MainDisplayState.ROOM_STATUS;
				Utils.hideKeyboard(MainActivity.this, etMessage);
				changeActionBarState(mDisplayState);
				DataManager.getInstance(MainActivity.this)
						.setCurrentChatUserId(null);
				hideNotice();
			}

			@Override
			public void onPanelAnchored(View panel) {
				// TODO Auto-generated method stub

			}
		});

		ibOption.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				hideDrawerMessages();
				if (mDisplayState == MainDisplayState.ROOM_STATUS) {

				} else if (mDisplayState == MainDisplayState.CHAT_PRIVATE) {
					showChatPrivateMenu();
				} else if (mDisplayState == MainDisplayState.CHAT_ROOM) {
					showChatRoomMenu();
				}
			}
		});

		rlMessages.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				mDrawerMessages.toggleMenu();
				Utils.hideKeyboard(MainActivity.this, etMessage);
			}
		});

		ibProfile.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				hideDrawerMessages();
				showEditProfileFragment();
			}
		});

		btImage.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showChooseImageFragment();
			}
		});

		lvMessages.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				HistoryMessage historyMessage = (HistoryMessage) parent
						.getAdapter().getItem(position);
				showChatPrivate(historyMessage.getMessageContent()
						.getFromUserID(), historyMessage.getMessageContent()
						.getName(), false);
			}
		});

		ibLogout.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				hideDrawerMessages();
				showLogoutDialog();
			}
		});
		llRoomMessageHistory.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showChatRoom();
			}
		});

		btFindchat.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				findUserIDInList.clear();
				isFindingChat = true;
				findFriendChatWithSetting(1, true);
			}
		});

		btSetting.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showSettingFragment();
			}
		});

		mAdViewChat.setAdListener(new AdListener() {
			@Override
			public void onAdLoaded() {
				mAdViewChat.setVisibility(View.VISIBLE);
				super.onAdLoaded();
			}

			@Override
			public void onAdFailedToLoad(int errorCode) {
				mAdViewChat.setVisibility(View.GONE);
				super.onAdFailedToLoad(errorCode);
			}
		});

		mAdViewMain.setAdListener(new AdListener() {
			@Override
			public void onAdLoaded() {
				mAdViewMain.setVisibility(View.VISIBLE);
				super.onAdLoaded();
			}

			@Override
			public void onAdFailedToLoad(int errorCode) {
				mAdViewMain.setVisibility(View.GONE);
				super.onAdFailedToLoad(errorCode);
			}
		});

		ibRefresh.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				clearUserData();
				getSuggestedUserOnline(1, 100);
			}
		});

		btFindFriendSetting.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				showFindFriendSettingFragment();
			}
		});

		interstitial.setAdListener(new AdListener() {
			@Override
			public void onAdFailedToLoad(int errorCode) {
				// TODO Auto-generated method stub
				super.onAdFailedToLoad(errorCode);
			}

			@Override
			public void onAdClosed() {
				AdRequest adRequest = new AdRequest.Builder().addTestDevice(
						AdRequest.DEVICE_ID_EMULATOR).build();
				interstitial.loadAd(adRequest);
			}
		});

		btClearMessage.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				hideDrawerMessages();
				showDeleteMessagesFragment();
			}
		});

		mDrawerMessages
				.setOnDrawerStateChangeListener(new OnDrawerStateChangeListener() {

					@Override
					public void onDrawerStateChange(int oldState, int newState) {
						if (newState == MenuDrawer.STATE_OPEN) {
							sendCheckFriendsOnline();
						}
					}

					@Override
					public void onDrawerSlide(float openRatio, int offsetPixels) {

					}
				});

	}

	protected void showChatRoomMenu() {
		AlertDialog.Builder aBuilder = new AlertDialog.Builder(
				MainActivity.this);
		aBuilder.setItems(new String[] { "Hide", "Change Room" },
				new Dialog.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						switch (which) {
						case 0:
							slidingLayout.collapsePanel();
							break;
						case 1:
							showChangeRoomDialog();
							break;
						default:
							break;
						}
					}
				});

		AlertDialog alertDialog = aBuilder.create();
		alertDialog.setCanceledOnTouchOutside(true);
		alertDialog.show();
	}

	protected void showChatPrivateMenu() {
		final Integer currentChatUserID = DataManager.getInstance(
				MainActivity.this).getCurrentChatUserId();
		if (currentChatUserID == null) {
			return;
		}
		final boolean isBlock = DataManager.getInstance(MainActivity.this)
				.getBlockUsers().contains(currentChatUserID);
		String blockMenu;
		String addFriendMenu;
		if (isBlock) {
			blockMenu = "Unblock this user";
		} else {
			blockMenu = "Block this user";
		}

		final boolean isFriend = MessagesDataManager.getInstance(
				MainActivity.this).checkIsFriend(currentChatUserID,
				currentChatName);
		if (isFriend) {
			addFriendMenu = "Remove friend";
		} else {
			addFriendMenu = "Add friend";
		}

		AlertDialog.Builder aBuilder = new AlertDialog.Builder(
				MainActivity.this);
		aBuilder.setItems(new String[] { "Hide", addFriendMenu, blockMenu,
				"Report this user" }, new Dialog.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				switch (which) {
				case 0:
					slidingLayout.collapsePanel();
					break;
				case 1:
					MessagesDataManager
							.getInstance(MainActivity.this)
							.markFriend(
									currentChatUserID,
									!MessagesDataManager.getInstance(
											MainActivity.this).checkIsFriend(
											currentChatUserID, currentChatName));
					refreshHistoryMessage();
					break;
				case 2:
					if (isBlock) {
						DataManager.getInstance(MainActivity.this)
								.removeBlockUsers(currentChatUserID);
						hideNotice();
					} else {
						DataManager.getInstance(MainActivity.this)
								.addBlockUsers(currentChatUserID);
						showNotice(false, "You blocked this user!", "Unblock");
						tvAction.setOnClickListener(new OnClickListener() {

							@Override
							public void onClick(View v) {
								DataManager.getInstance(MainActivity.this)
										.removeBlockUsers(currentChatUserID);
								hideNotice();
							}
						});
					}

					break;
				case 3:
					Utils.reportUser(currentChatUserID);
					break;
				default:
					break;
				}
			}
		});

		AlertDialog alertDialog = aBuilder.create();
		alertDialog.setCanceledOnTouchOutside(true);
		alertDialog.show();
	}

	private void clearUserData() {
		userData.clear();
		currentUserIDsInList.clear();
		userAdapter.notifyDataSetChanged();
	}

	private void getSuggestedUserOnline(int page, final int size) {
		ibRefresh.startAnimation(animationRotate);
		ibRefresh.setEnabled(false);
		ArrayList<String> userTags = new ArrayList<String>();
		userTags.add(ChatService.ONLINE);
		userTags.add(ChatService.VISIBLE);
		// userTags.add(ChatService.USER);
		QBPagedRequestBuilder pagedRequestBuilder = new QBPagedRequestBuilder();
		pagedRequestBuilder.setPage(page);
		pagedRequestBuilder.setPerPage(size);
		QBUsers.getUsersByTags(userTags, pagedRequestBuilder,
				new QBEntityCallbackImpl<ArrayList<QBUser>>() {
					@Override
					public void onSuccess(ArrayList<QBUser> users, Bundle params) {
						if (users == null || users.size() == 0) {

						} else {
							// Collections.shuffle(users);
							for (QBUser user : users) {
								if (isValidSuggestedUser(user)) {
									currentUserIDsInList.add(user.getId());
									userData.add(convertQBUserToUser(user));
								}

							}
							userAdapter.notifyDataSetChanged();

							int currentPage = params.getInt(Consts.CURR_PAGE);
							int perPage = params.getInt(Consts.PER_PAGE);
							int totalPage = (params
									.getInt(Consts.TOTAL_ENTRIES) / perPage) + 1;

							if (userData.size() < size
									&& currentPage < totalPage) {
								getSuggestedUserOnline(currentPage + 1, 100);
							} else {
								ibRefresh.clearAnimation();
								ibRefresh.setEnabled(true);
								if (!DataManager.getInstance(MainActivity.this)
										.isShowPost()) {
									showSayHi();
									DataManager.getInstance(MainActivity.this)
											.setIsShowPost(true);
								}
							}
						}
					}

					@Override
					public void onError(List<String> errors) {
						KiraGameLog.d("getSuggestedUserOnline error " + errors);
						ibRefresh.clearAnimation();
						ibRefresh.setEnabled(true);
						if (!DataManager.getInstance(MainActivity.this)
								.isShowPost()) {
							showSayHi();
							DataManager.getInstance(MainActivity.this)
									.setIsShowPost(true);
						}
					}
				});
	}

	protected User convertQBUserToUser(QBUser user) {
		User xchatUser = new User();
		xchatUser.setUserID(user.getId());
		xchatUser.setName(user.getFullName());
		UserInfo userInfo;
		if (user.getCustomData() != null) {
			try {
				userInfo = UserInfo.fromJsonToUserInfo(user.getCustomData());
			} catch (Exception e) {
				userInfo = new UserInfo();
				userInfo.setGender(GenderType.FEMALE);
				userInfo.setStatus("Hi! I'm Female");
			}

		} else {
			userInfo = Utils.getUserInfoFromQBWebsite(user.getWebsite());
		}
		xchatUser.setUserInfo(userInfo);
		return xchatUser;

	}

	private boolean isOnline(QBUser user) {
		long currentTime = System.currentTimeMillis();
		long userLastRequestAtTime = user.getLastRequestAt().getTime();

		// if user didn't do anything last 5 minutes (5*60*1000 milliseconds)
		if ((currentTime - userLastRequestAtTime) > 5 * 60 * 1000) {
			return false;
		}
		return true;
	}

	public boolean isValidSuggestedUser(QBUser user) {
		if (!isOnline(user)) {
			return false;
		}

		if (DataManager.getInstance(MainActivity.this).getBlockUsers()
				.contains(user.getId())) {
			return false;
		}
		if (currentUserIDsInList.contains(user.getId())) {
			return false;
		}
		return true;
	}

	private void sendChatTyping() {
		if (isTyping) {
			return;
		}
		isTyping = true;
		Integer chatToUser = DataManager.getInstance(MainActivity.this)
				.getCurrentChatUserId();
		if (chatToUser == null) {
			return;
		}
		ChatService.getInstance().sendMessage(chatToUser, null,
				MsgType.SEND_TYPING, false);
		new CountDownTimer(3000, 1000) {

			@Override
			public void onTick(long millisUntilFinished) {

			}

			@Override
			public void onFinish() {
				sendChatStopTyping();
			}
		}.start();
	}

	private void sendChatStopTyping() {
		isTyping = false;
		Integer chatToUser = DataManager.getInstance(MainActivity.this)
				.getCurrentChatUserId();
		if (chatToUser == null) {
			return;
		}
		ChatService.getInstance().sendMessage(chatToUser, null,
				MsgType.SEND_STOP_TYPING, false);
	}

	public void showChatPrivate(final Integer userID, final String name,
			boolean isNotify) {
		if (userID == null) {
			return;
		}
		sendChatStopTyping();
		mDisplayState = MainDisplayState.CHAT_PRIVATE;
		// Update new message num;
		resetUnreadNumMessageFragment(userID);

		setOnlineState(false);
		sendCheckOnline(userID);
		hideDrawerMessages();
		Integer currentChatUserID = DataManager.getInstance(this)
				.getCurrentChatUserId();
		currentChatName = name;
		DataManager.getInstance(this).setCurrentChatUserId(userID);
		final boolean isBlock = DataManager.getInstance(MainActivity.this)
				.getBlockUsers().contains(userID);
		if (isBlock) {
			showNotice(false, "You blocked this user!", "Unblock");
			tvAction.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					DataManager.getInstance(MainActivity.this)
							.removeBlockUsers(userID);
					hideNotice();
				}
			});
		} else {
			hideNotice();
		}

		if (!isNotify
				&& ((currentChatUserID != null && currentChatUserID
						.equals(userID)) || userID.equals(DataManager
						.getInstance(this).getUserID()))) {
			return;
		}

		// snRoom.setVisibility(View.GONE);
		// tvTitle.setVisibility(View.VISIBLE);
		tvTitle.setText(name);
		changeActionBarState(mDisplayState);
		btImage.setVisibility(View.VISIBLE);
		if (slidingLayout != null && !slidingLayout.isPanelExpanded()) {
			slidingLayout.expandPanel();
		}

		lvChat.setAdapter(chatPrivateAdapter);
		messageContentPrivateData.clear();
		messageContentPrivateData.addAll(MessagesDataManager.getInstance(this)
				.getMessages(Integer.toString(userID), 0, 10));
		chatPrivateAdapter.notifyDataSetChanged();
		MessagesDataManager.getInstance(MainActivity.this)
				.checkIsFriend(userID, name);
		refreshHistoryMessage();
	}

	private void sendCheckOnline(Integer currentChatUserID) {
		ChatService.getInstance().sendMessage(currentChatUserID, "",
				MsgType.CHECK_USER_ONLINE, false);
	}

	private void setOnlineState(boolean isOnline) {
		if (isOnline) {
			ibOnline.setImageResource(R.drawable.ic_online);
			ibOnline.setVisibility(View.VISIBLE);
		} else {
			ibOnline.setImageResource(R.drawable.ic_offline);
			ibOnline.setVisibility(View.GONE);
		}
	}

	private void refreshHistoryMessage() {
		loadMessageFromDatabase();
	}

	private void sendCheckFriendsOnline() {
		for (HistoryMessage historyMessage : historyMessageData) {
			ChatService.getInstance().sendMessage(
					historyMessage.getMessageContent().getFromUserID(), "",
					MsgType.CHECK_FRIEND_ONLINE, false);
		}
	}

	private BroadcastReceiver changeUIReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			String actionUIMAin = intent
					.getStringExtra(ChatService.CONTROL_ACTION);
			String message = intent.getStringExtra(ChatService.CONTROL_MESSAGE);
			KiraGameLog.d("get broadcast receive with action " + actionUIMAin
					+ " and message " + message);
			switch (actionUIMAin) {
			case ChatService.MAIN_ACTION_ON_PRE_UPDATE_PROFILE:
				onPreUpdateProfile();
				break;
			case ChatService.MAIN_ACTION_ON_FINISHED_UPDATE_PROFILE:
				onFinishedUpdateProfile(message);
				break;
			case ChatService.MAIN_ACTION_ON_PRE_JOIN_ROOM:
				onPreJoinRoom();
				break;
			case ChatService.MAIN_ACTION_ON_FINISHED_JOIN_ROOM:
				onFinishedJoinRoom(message);
				break;
			case ChatService.MAIN_ACTION_ON_PRE_LOG_OUT:
				onPreLogOut();
				break;
			case ChatService.MAIN_ACTION_ON_FINISHED_LOG_OUT:
				onFinishedLogOut(message);
				break;
			case ChatService.MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_ROOM_FRAGMENT:
				updateMessageInChatRoom(message);
				break;
			case ChatService.MAIN_ACTION_UPDATE_MESSAGES_IN_MESSAGE_FRAGMENT:
				updateMessageInMessagesFragment(message);
				break;
			case ChatService.MAIN_ACTION_UPDATE_MESSAGES_IN_CHAT_PRIVATE:
				updateListMessageInChatPrivate(message);
				break;
			case ChatService.MAIN_ACTION_NOTIFY_CONNECTION_ONLINE:
				notifyConnectionOnline();
				break;
			case ChatService.MAIN_ACTION_NOTIFY_CONNECTION_OFFLINE:
				notifyConnectionOffline();
				break;
			case ChatService.MAIN_ACTION_RECEIVE_SAY_HI_REQUEST:
				receiveSayHiRequest(message);
				break;
			default:
				break;
			}
		}
	};

	// CALLBACK FROM CHAT SERVICE

	private void notifyConnectionOffline() {
		KiraGameLog.d("No Internet connection!");
		showNotice(false, "No Internet Connection!", "WIFI SETTING");
		tvAction.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
				startActivity(intent);
			}
		});
	}

	private void notifyConnectionOnline() {
		KiraGameLog.d("Internet connection successful!");
		hideNotice();
	}

	private void receiveSayHiRequest(String message) {
		KiraGameLog.d("receiveSayHiRequest from " + message);
		MessageContent msg = MessageContent.fromJsonToMessageContent(message);
		if (msg == null) {
			return;
		}

		User fromUser = null;
		try {
			fromUser = User.fromJsonToUser(msg.getContent());
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (fromUser == null) {
			return;
		}
		GenderType searchGender = DataManager.getInstance(this)
				.getGenderSearch();

		if (isFindingChat) {
			if (searchGender == GenderType.ANY
					|| (searchGender == fromUser.getUserInfo().getGender())) {
				showChatPrivate(msg.getFromUserID(), msg.getName(), true);
				isFindingChat = false;
				hideNotice();
				ChatService.getInstance().sendMessage(msg.getFromUserID(),
						DataManager.getInstance(this).getUser().toJson(),
						MsgType.SAY_HI_REQUEST, false);
			}
		}
	}

	private void onFinishedJoinRoom(String error) {
		if (error != null) {
			// ERROR
			showNotice(false, error, "RETRY");
			// update profile fail. try again?
			tvAction.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					hideNotice();
					RoomType currentRoom = DataManager.getInstance(
							MainActivity.this).getCurrentRoom();
					ChatService.getInstance().joinroom(
							Common.listRoomId[currentRoom.ordinal()], false);
				}
			});
		} else {
			// tvNameRoomMessageHistory.setText("Room "
			// + snRoom.getSelectedItem().toString());
			hideNotice();
			llRoomMessageHistory.setVisibility(View.VISIBLE);
			// ChatService.getInstance().getUserOnlineInRoom(1, 100);sdfdsfdsfds
		}
	}

	private void onPreJoinRoom() {
		showNotice(true, "Joining room...", null);
		llRoomMessageHistory.setVisibility(View.GONE);
		messageContentRoomData.clear();
		userAdapter.notifyDataSetChanged();
		chatRoomAdapter.notifyDataSetChanged();

		// Reset new room message num in message fragment
		newRoomMessageHistory = 0;
		tvMessageNumRoomMessageHistory.setVisibility(View.GONE);

		// Update new message num in message fragment
		updateNewMessagesNum();
		changeActionBarState(mDisplayState);
	}

	private void onFinishedUpdateProfile(String error) {
		hideNotice();
		if (error != null) {
			// ERROR
			showNotice(false, error, "RETRY");
			// update profile fail. try again?
			tvAction.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					hideNotice();
					showEditProfileFragment();
				}
			});
		} else {
			updateInfoInRoom();
			// sendChatToRoom();
		}
	}

	private void onPreUpdateProfile() {
		showNotice(true, "Updating profile...", null);
	}

	private void onPreLogOut() {
		showNotice(true, "Logout...", null);
	}

	private void onFinishedLogOut(String error) {
		hideNotice();
	}

	// ROOM
	private void updateMessageInChatRoom(String message) {
		if (message != null) {
			MessageContent messageContent = MessageContent
					.fromJsonToMessageContent(message);
			if (messageContent == null) {
				return;
			}
			if (messageContent.getMsgType() == MsgType.TEXT
					|| messageContent.getMsgType() == MsgType.IMAGE) {
				messageContentRoomData.add(messageContent);
				chatRoomAdapter.notifyDataSetChanged();
				// Update new message room in Message fragment
				if (mDisplayState != MainDisplayState.CHAT_ROOM) {
					newRoomMessageHistory++;

					if (messageContent.getMsgType() == MsgType.TEXT) {
						tvMessageRoomMessageHistory.setText(Emoticons
								.getSmiledText(this,
										messageContent.getContent()));
					} else {
						tvMessageRoomMessageHistory.setText("Send an image!");
					}

					if (newRoomMessageHistory > 10) {
						tvMessageNumRoomMessageHistory.setText("9+");
						tvMessageNumRoomMessageHistory
								.setVisibility(View.VISIBLE);
					} else if (newRoomMessageHistory > 0) {
						tvMessageNumRoomMessageHistory.setText(String
								.valueOf(newRoomMessageHistory));
						tvMessageNumRoomMessageHistory
								.setVisibility(View.VISIBLE);
					} else {
						tvMessageNumRoomMessageHistory.setVisibility(View.GONE);
					}
					updateNewMessagesNum();
				}

			} else if (messageContent.getMsgType() == MsgType.UPDATE_INFO) {
				updateUserInfoInRoomStatus(User.fromJsonToUser(messageContent
						.getContent()));
			} else if (messageContent.getMsgType() == MsgType.ONLINE) {
				User user = User.fromJsonToUser(messageContent.getContent());
				onUserEnteredRoom(user);
			} else if (messageContent.getMsgType() == MsgType.OFFLINE) {
				onUserLeftRoom(messageContent.getFromUserID());
			}

		}

	}

	private void showChatRoom() {
		mDisplayState = MainDisplayState.CHAT_ROOM;

		// Reset new room message num in message fragment
		newRoomMessageHistory = 0;
		tvMessageNumRoomMessageHistory.setVisibility(View.GONE);

		// Update new message num in message fragment
		updateNewMessagesNum();

		// Set coming message go to history message fragment
		DataManager.getInstance(this).setCurrentChatUserId(null);

		changeActionBarState(mDisplayState);
		btImage.setVisibility(View.GONE);
		hideDrawerMessages();
		lvChat.setAdapter(chatRoomAdapter);
		if (slidingLayout != null && !slidingLayout.isPanelExpanded()) {
			slidingLayout.expandPanel();
		}
	}

	public void updateListUserInRoom(String message) {
		if (message != null) {
			userData.addAll(User.fromJsonArrayToUsers(message));
		}
		userAdapter.notifyDataSetChanged();
	}

	public void onUserEnteredRoom(User mUser) {
		if (!currentUserIDsInList.contains(mUser.getUserID())) {
			currentUserIDsInList.add(mUser.getUserID());
			List<User> users = new ArrayList<User>();
			users.add(mUser);
			updateListUserInRoom(User.toJsonArray(users));
		}

	}

	public void onUserLeftRoom(Integer id) {
		if (currentUserIDsInList.contains(id)) {
			currentUserIDsInList.remove(id);
			Iterator<User> user = userData.iterator();
			while (user.hasNext()) {
				User mUser = (User) user.next();
				if (id.equals(mUser.getUserID())) {
					user.remove();
					break;
				}
			}
			userAdapter.notifyDataSetChanged();
		}

	}

	private void updateInfoInRoom() {
		// Send message update room to user in room
		ChatService.getInstance().sendMessageChatRoom(
				DataManager.getInstance(this).getUser().toJson(),
				MsgType.UPDATE_INFO);
	}

	private void updateUserInfoInRoomStatus(User userInfoUpdated) {
		for (User user : userData) {
			if (user.getUserID().equals(userInfoUpdated.getUserID())) {
				user.setName(userInfoUpdated.getName());
				UserInfo userInfo = new UserInfo();
				userInfo.setStatus(userInfoUpdated.getUserInfo().getStatus());
				userInfo.setGender(userInfoUpdated.getUserInfo().getGender());
				user.setUserInfo(userInfo);
				break;
			}
		}
		userAdapter.notifyDataSetChanged();
	}

	// MESSAGE FRAGMENT
	private View getMessagesView() {
		View view = getLayoutInflater().inflate(R.layout.fragment_messages,
				null);
		findViewIdsMessageFragment(view);
		initMessageFragment();
		return view;
	}

	private void initMessageFragment() {
		historyMessageAdapter = new HistoryMessageAdapter(this,
				historyMessageData);
		lvMessages.setAdapter(historyMessageAdapter);
		refreshHistoryMessage();
	}

	private void findViewIdsMessageFragment(View view) {
		lvMessages = (ListView) view.findViewById(R.id.lv_messages);
		ibLogout = (ImageButton) view.findViewById(R.id.ib_logout);
		tvMessageRoomMessageHistory = (TextView) view
				.findViewById(R.id.tv_message);
		tvMessageNumRoomMessageHistory = (TextView) view
				.findViewById(R.id.tv_message_num);
		llRoomMessageHistory = (LinearLayout) view
				.findViewById(R.id.ll_room_message_history);
		btSetting = (Button) view.findViewById(R.id.bt_setting);
		btClearMessage = (ImageButton) view.findViewById(R.id.bt_clear_message);
	}

	private void loadMessageFromDatabase() {
		historyMessageData.clear();
		historyMessageData.addAll(MessagesDataManager.getInstance(this)
				.getAllHistoryMessages(0, 50));
		historyMessageAdapter.notifyDataSetChanged();
		updateNewMessagesNum();
	}

	private void updateNewMessagesNum() {
		int newMessagesNum = 0;
		for (HistoryMessage historyMessage : historyMessageData) {
			newMessagesNum = newMessagesNum + historyMessage.getUnreadNum();
		}
		if (newRoomMessageHistory > 0) {
			newMessagesNum = newMessagesNum + 1;
		}
		if (newMessagesNum > 9) {
			tvNumMessage.setText("9+");
			tvNumMessage.setVisibility(View.VISIBLE);
		} else if (newMessagesNum > 0) {
			tvNumMessage.setText(Integer.toString(newMessagesNum));
			tvNumMessage.setVisibility(View.VISIBLE);
		} else {
			tvNumMessage.setVisibility(View.GONE);
		}
	}

	private void updateMessageInMessagesFragment(String message) {
		// boolean isExist = false;
		if (message != null) {
			MessageContent msg = MessageContent
					.fromJsonToMessageContent(message);
			if (msg == null) {
				return;
			}
			if (!msg.getFromUserID().equals(
					DataManager.getInstance(this).getUserID())) {
				if (DataManager.getInstance(this).getVibrationSetting()) {
					long[] pattern = { 0, 100 };
					vibrator.vibrate(pattern, -1);
				}
			}

			// Update HISTORY CHAT
			for (int i = 0; i < historyMessageData.size(); i++) {
				HistoryMessage historyMessage = historyMessageData.get(i);
				if (historyMessage.getMessageContent().getFromUserID()
						.equals(msg.getFromUserID())) {
					// exist ->update
					int num = historyMessage.getUnreadNum() + 1;
					historyMessage.setMessageContent(msg);
					historyMessage.setUnreadNum(num);
					Collections.swap(historyMessageData, i, 0);
					historyMessageAdapter.notifyDataSetChanged();
					MessagesDataManager.getInstance(this).updateHistoryMessage(
							msg.getFromUserID(), msg, num);
					updateNewMessagesNum();
					return;
				}
			}
			// NOTICE: NOT WRITE CODE BELOW HERE, IT MAY BE NOT RUN BY "RETURN"
			// not exist insert new
			HistoryMessage historyMessage = new HistoryMessage();
			historyMessage.setMessageContent(msg);
			historyMessage.setUnreadNum(1);
			historyMessageData.add(0, historyMessage);
			historyMessageAdapter.notifyDataSetChanged();
			MessagesDataManager.getInstance(this).insertHistoryMessage(
					msg.getFromUserID(), msg, 1, false);
			updateNewMessagesNum();
			// NOTICE: NOT WRITE CODE BELOW HERE, IT MAY BE NOT RUN BY "RETURN"
		}

	}

	private void resetUnreadNumMessageFragment(Integer userID) {
		for (HistoryMessage historyMessage : historyMessageData) {
			if (historyMessage.getMessageContent().getFromUserID()
					.equals(userID)) {
				historyMessage.setUnreadNum(0);
				historyMessageAdapter.notifyDataSetChanged();
				break;
			}
		}
		MessagesDataManager.getInstance(this).resetHistoryMessageUnreadNum(
				userID);
		updateNewMessagesNum();
	}

	// CHAT PRIVATE
	private void updateListMessageInChatPrivate(String message) {
		if (message != null) {
			MessageContent messageContent = MessageContent
					.fromJsonToMessageContent(message);
			if (messageContent == null) {
				return;
			}
			if (messageContent.getMsgType() == MsgType.SEND_TYPING) {
				showChatTyping();
			} else if (messageContent.getMsgType() == MsgType.SEND_STOP_TYPING) {
				hideChatTyping();
			} else if (messageContent.getMsgType() == MsgType.CHECK_USER_ONLINE) {
				sendUserOnlineStatus(messageContent.getFromUserID());
			} else if (messageContent.getMsgType() == MsgType.USER_ONLINE) {
				updateOnlineStatusCurrentChat(messageContent.getFromUserID());
			} else if (messageContent.getMsgType() == MsgType.CHECK_FRIEND_ONLINE) {
				sendFriendOnlineStatus(messageContent.getFromUserID());
			} else if (messageContent.getMsgType() == MsgType.FRIEND_ONLINE) {
				updateOnlineStatusFriendList(messageContent.getFromUserID());
			} else {
				hideChatTyping();
				messageContentPrivateData.add(messageContent);

				chatPrivateAdapter.notifyDataSetChanged();

				if (!messageContent.getFromUserID().equals(
						DataManager.getInstance(this).getUserID())) {
					if (DataManager.getInstance(this).getVibrationSetting()) {
						long[] pattern = { 0, 100 };
						vibrator.vibrate(pattern, -1);
					}
				}
			}

		}

	}

	private void updateOnlineStatusFriendList(Integer fromUserID) {
		for (HistoryMessage historyMessage : historyMessageData) {
			if (historyMessage.getMessageContent().getFromUserID()
					.equals(fromUserID)) {
				historyMessage.setOnline(true);
				historyMessageAdapter.notifyDataSetChanged();
				return;
			}
		}
	}

	private void sendFriendOnlineStatus(Integer fromUserID) {
		ChatService.getInstance().sendMessage(fromUserID, "",
				MsgType.FRIEND_ONLINE, false);
	}

	private void updateOnlineStatusCurrentChat(Integer fromUserID) {
		Integer currentChatUserID = DataManager.getInstance(this)
				.getCurrentChatUserId();
		if (fromUserID.equals(currentChatUserID)) {
			setOnlineState(true);
		}
	}

	private void sendUserOnlineStatus(Integer fromUserID) {
		ChatService.getInstance().sendMessage(fromUserID, "",
				MsgType.USER_ONLINE, false);
	}

	private void hideChatTyping() {
		tvTyping.setVisibility(View.GONE);
	}

	private void showChatTyping() {
		tvTyping.setVisibility(View.VISIBLE);
		tvTyping.setText(currentChatName + " is typing...");
	}

	private void findFriendChatWithSetting(int page, boolean isShowNotice) {
		hideDrawerMessages();
		if (!isFindingChat) {
			return;
		}
		if (isShowNotice) {
			showNotice(true, "Finding chat friend...", "Cancel");
			tvAction.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					isFindingChat = false;
					hideNotice();
				}
			});
		}

		GenderType genderSearch = DataManager.getInstance(this)
				.getGenderSearch();
		ArrayList<String> userTags = new ArrayList<String>();
		userTags.add(ChatService.ONLINE);
		// userTags.add(ChatService.USER);
		if (genderSearch == GenderType.FEMALE) {
			userTags.add(UserInfo.genderText[GenderType.FEMALE.ordinal()]);
		} else if (genderSearch == GenderType.MALE) {
			userTags.add(UserInfo.genderText[GenderType.MALE.ordinal()]);
		}

		QBPagedRequestBuilder pagedRequestBuilder = new QBPagedRequestBuilder();
		pagedRequestBuilder.setPage(page);
		pagedRequestBuilder.setPerPage(100);
		final Integer currentUserID = DataManager
				.getInstance(MainActivity.this).getUserID();

		QBUsers.getUsersByTags(userTags, pagedRequestBuilder,
				new QBEntityCallbackImpl<ArrayList<QBUser>>() {

					@Override
					public void onSuccess(ArrayList<QBUser> users, Bundle params) {
						if (users == null || users.size() == 0) {
						} else {
							Collections.shuffle(users);
							for (QBUser qbUser : users) {
								if (isOnline(qbUser)
										&& !qbUser.getId()
												.equals(currentUserID)
										&& !findUserIDInList.contains(qbUser
												.getId())) {
									findUserIDInList.add(qbUser.getId());
									KiraGameLog.d("send hi request to "
											+ qbUser);
									ChatService.getInstance().sendMessage(
											qbUser.getId(),
											DataManager
													.getInstance(
															MainActivity.this)
													.getUser().toJson(),
											MsgType.SAY_HI_REQUEST, false);
								}
							}

							int currentPage = params.getInt(Consts.CURR_PAGE);
							int perPage = params.getInt(Consts.PER_PAGE);
							int totalPage = (params
									.getInt(Consts.TOTAL_ENTRIES) / perPage) + 1;

							if (currentPage < totalPage) {
								findFriendChatWithSetting(currentPage + 1,
										false);
								return;
							} else {
								if (isFindingChat) {
									new CountDownTimer(1000 * 30, 1000) {
										@Override
										public void onTick(
												long millisUntilFinished) {
											if (!isFindingChat) {
												this.cancel();
											}
										}

										@Override
										public void onFinish() {
											findFriendChatLv2();
										}
									}.start();
								}
							}
						}

					}

					@Override
					public void onError(List<String> errors) {
						// handleErrors(errors);
						KiraGameLog.d("findFriendChatWithSetting error "
								+ errors);
						findFriendChatLv2();
					}
				});
	}

	protected void findFriendChatLv2() {
		if (findUserIDInList.size() == 0) {
			isFindingChat = false;
			hideNotice();
			return;
		}
		List<Integer> userSeachLv2 = new ArrayList<Integer>();
		userSeachLv2.addAll(findUserIDInList);
		Collections.shuffle(userSeachLv2);
		if (userSeachLv2.size() > 20) {
			userSeachLv2 = userSeachLv2.subList(0, 20);
		}
		QBPagedRequestBuilder pagedRequestBuilder = new QBPagedRequestBuilder();
		pagedRequestBuilder.setPage(1);
		pagedRequestBuilder.setPerPage(20);

		QBUsers.getUsersByIDs(userSeachLv2, pagedRequestBuilder,
				new QBEntityCallbackImpl<ArrayList<QBUser>>() {
					@Override
					public void onSuccess(ArrayList<QBUser> users, Bundle params) {
						List<User> xchatUsers = new ArrayList<User>();
						for (QBUser user : users) {
							xchatUsers.add(convertQBUserToUser(user));
						}
						if (isFindingChat) {
							showFindFriendResultsFragment(xchatUsers);
						}

						isFindingChat = false;
						hideNotice();
					}

					@Override
					public void onError(List<String> errors) {
						KiraGameLog.d("Get user by ids error: " + errors);
						isFindingChat = false;
						hideNotice();
					}

				});
	}

	private void sendChatToRoom() {
		ChatService.getInstance().sendMessageChatRoom(
				DataManager.getInstance(this).getUserStatus(), MsgType.TEXT);
	}

	private void hideDrawerMessages() {
		if (mDrawerMessages.isMenuVisible()) {
			mDrawerMessages.toggleMenu();
		}
	}

	private void sendImageChat(String url) {
		if (url != null) {

			if (mDisplayState == MainDisplayState.CHAT_ROOM) {
				return;
				// Chat room
				// ChatService.getInstance().sendMessageChatRoom(url,
				// MsgType.IMAGE);
				// lvChat.setSelection(chatPrivateAdapter.getCount() - 1);

			} else if (mDisplayState == MainDisplayState.CHAT_PRIVATE) {
				// Chat private
				Integer sendTo = DataManager.getInstance(this)
						.getCurrentChatUserId();
				if (sendTo == null) {
					return;
				}
				ChatService.getInstance().sendMessage(sendTo, url,
						MsgType.IMAGE, true);
				lvChat.setSelection(chatPrivateAdapter.getCount() - 1);
			} else {
				return;
			}

		}
	}

	private void showNotice(boolean isShowProgessbar, String message,
			String action) {
		if (isShowProgessbar) {
			pbLoading.setVisibility(View.VISIBLE);
		} else {
			pbLoading.setVisibility(View.GONE);
		}
		if (message != null) {
			tvNotice.setText(message);
		}
		if (action != null) {
			tvAction.setText(action);
			tvAction.setVisibility(View.VISIBLE);
			vSplit.setVisibility(View.VISIBLE);
		} else {
			tvAction.setVisibility(View.GONE);
			vSplit.setVisibility(View.GONE);
		}

		llNotice.setVisibility(View.VISIBLE);
		llNotice.startAnimation(animationShow);
	}

	private void hideNotice() {
		if (llNotice.getVisibility() == View.GONE) {
			return;
		}
		animationHide.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
			}

			@Override
			public void onAnimationEnd(Animation animation) {
				llNotice.setVisibility(View.GONE);
			}
		});
		llNotice.startAnimation(animationHide);
	}

	private void showEditProfileFragment() {
		try {
			final EditProfileDialogFragment dialog = new EditProfileDialogFragment();
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "EditProfileDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void showSettingFragment() {
		try {
			hideDrawerMessages();
			final SettingDialogFragment dialog = new SettingDialogFragment();
			dialog.setOnSettingDialogFragment(new OnSettingDialogFragment() {

				@Override
				public void onDontShowSettingChange(boolean mIsInvisible) {
					boolean isInvisible = DataManager.getInstance(
							MainActivity.this).getInvisibleSetting();
					RoomType room = DataManager.getInstance(MainActivity.this)
							.getCurrentRoom();
					ChatService.getInstance().updateProfile(true, isInvisible,
							room);
					if (isInvisible) {
						ChatService.getInstance().sendOfflineStatusToRoom();
					} else {
						ChatService.getInstance().sendOnlineStatusToRoom();
					}
				}
			});
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "SettingDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void showChooseImageFragment() {
		try {
			final ChooseImageDialogFragment dialog = new ChooseImageDialogFragment();
			dialog.setOnChooseImageDialogFragment(new OnChooseImageDialogFragment() {

				@Override
				public void onGallery() {
					selectImageFromGallery();
				}

				@Override
				public void onCamera() {
					selectImageFromCamera();
				}
			});
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "ChooseImageDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void selectImageFromGallery() {
		Intent intent = new Intent(this, ProcessImage.class);
		intent.putExtra(ProcessImage.IS_SELECT_IMAGE_FROM_CAMERA, false);
		intent.putExtra(ProcessImage.ASPECT_RATIO_X, 0);
		intent.putExtra(ProcessImage.ASPECT_RATIO_Y, 0);
		startActivityForResult(intent, Common.RequestCode.CHAT_IMAGE);
	}

	private void selectImageFromCamera() {
		Intent intent = new Intent(this, ProcessImage.class);
		intent.putExtra(ProcessImage.IS_SELECT_IMAGE_FROM_CAMERA, true);
		intent.putExtra(ProcessImage.ASPECT_RATIO_X, 0);
		intent.putExtra(ProcessImage.ASPECT_RATIO_Y, 0);
		startActivityForResult(intent, Common.RequestCode.CHAT_IMAGE);
	}

	private void showFindFriendSettingFragment() {
		try {
			final FindFriendSettingDialogFragment dialog = new FindFriendSettingDialogFragment();
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "FindFriendSettingDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void showDeleteMessagesFragment() {
		try {
			final DeleteMessageDialogFragment dialog = new DeleteMessageDialogFragment();
			dialog.setOnDeleteMessagesDialogFragment(new onDeleteMessagesDialogFragment() {

				@Override
				public void onDeleteMessage() {
					MessagesDataManager.getInstance(MainActivity.this)
							.deleteHistoryMessageUnMarkFriend();
					refreshHistoryMessage();
				}
			});
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "DeleteMessageDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void viewProfile(User user) {
		try {
			final ViewProfileFragment dialog = ViewProfileFragment
					.newInstance(user);
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "ViewProfileFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void showFindFriendResultsFragment(List<User> users) {

		try {
			if (users.size() == 0) {
				return;
			}
			final FindFriendResultsFragment dialog = FindFriendResultsFragment
					.newInstance(users);
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "FindFriendResultsFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void showExitDialog() {
		try {
			final ExitConfirmDialogFragment dialog = new ExitConfirmDialogFragment();
			dialog.setCancelable(false);
			dialog.setOnExitDialogListener(new OnExitDialogListener() {

				@Override
				public void onCancel() {
				}

				@Override
				public void onExit() {
					ChatService.getInstance().exit();
					finish();
				}
			});
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "ExitConfirmDialogFragment");
			transaction.commitAllowingStateLoss();

			// Random rnd = new Random();
			// int random = rnd.nextInt(3);
			// if ((!DataManager.getInstance(this).isRatedApp()) && (random ==
			// 2)) {
			// FragmentTransaction transaction2 = getSupportFragmentManager()
			// .beginTransaction();
			// final RateAppDialogFragment rateAppDialogFragment = new
			// RateAppDialogFragment();
			// transaction2.add(rateAppDialogFragment, "rateAppDialogFragment");
			// transaction2.commitAllowingStateLoss();
			// }
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void showLogoutDialog() {
		try {
			final LogoutConfirmDialogFragment dialog = new LogoutConfirmDialogFragment();
			dialog.setCancelable(false);
			dialog.setOnExitDialogListener(new OnLogoutDialogListener() {

				@Override
				public void onExit() {
					DataManager.getInstance(MainActivity.this).setIsShowPost(
							false);
					DataManager.getInstance(MainActivity.this)
							.setIsLogout(true);
					ChatService.getInstance().logOut();
					finish();
				}

				@Override
				public void onCancel() {

				}
			});
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "LogoutConfirmDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void showChangeRoomDialog() {
		try {
			final ChooseRoomDialogFragment dialog = new ChooseRoomDialogFragment();
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "ChooseRoomDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private void showSayHi() {
		try {
			final SayHiDialogFragment dialog = new SayHiDialogFragment();
			dialog.setCancelable(false);
			dialog.setOnSayHiDialogFragment(new OnSayHiDialogFragment() {

				@Override
				public void onCancel() {
					// findFriendChat();
					sendChatToRoom();
				}
			});
			FragmentTransaction transaction = getSupportFragmentManager()
					.beginTransaction();
			transaction.add(dialog, "SayHiDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}
